package com.xu.wemall.easyexcel;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellExtra;
import com.baomidou.mybatisplus.extension.api.Assert;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

@Data
@Slf4j
@EqualsAndHashCode(callSuper = true)
public class ExcelEventListener<TableDto> extends AnalysisEventListener<TableDto> {

    public ExcelEventListener() {
    }

    private List<TableDto> list = new ArrayList<>();

    private List<CellExtra> cellExtraList = new ArrayList<>();

    @Override
    public void invoke(TableDto excelData, AnalysisContext analysisContext) {
        log.info(" data -> {}", excelData);
        list.add(excelData);
    }

    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        log.info(" extra -> {}", extra);

        int firstRowIndex = extra.getFirstRowIndex();
        int lastRowIndex = extra.getLastRowIndex();
        int firstColumnIndex = extra.getFirstColumnIndex();
        int lastColumnIndex = extra.getLastColumnIndex();
        log.info("firstRowIndex:{}, lastRowIndex:{}, firstColumnIndex:{},  lastColumnIndex:{}",
                firstRowIndex, lastRowIndex, firstColumnIndex, lastColumnIndex);

        CellExtraTypeEnum type = extra.getType();
        switch (type) {
            case MERGE: {
                if (extra.getRowIndex() >= HEAD_ROW_NUM) {
                    cellExtraList.add(extra);
                }
                break;
            }
            case COMMENT:
                log.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),
                        extra.getText());
                break;
            case HYPERLINK:
                if ("Sheet1!A1".equals(extra.getText())) {
                    log.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),
                            extra.getColumnIndex(), extra.getText());
                } else if ("Sheet2!A1".equals(extra.getText())) {
                    log.info(
                            "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"
                                    + "内容是:{}",
                            extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
                            extra.getLastColumnIndex(), extra.getText());
                } else {
                    Assert.fail("Unknown hyperlink!");
                }
                break;
            default: {
            }
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info(" doAfterAllAnalysed");

        //读取完成 填充合并过的单元格
        if (cellExtraList != null && !cellExtraList.isEmpty()) {
            mergeExcelData(list, cellExtraList);
        }
    }


    private static final int HEAD_ROW_NUM = 1;

    private void mergeExcelData(List<TableDto> excelDataList, List<CellExtra> cellExtraList) {
        cellExtraList.forEach(cellExtra -> {
            int firstRowIndex = cellExtra.getFirstRowIndex() - HEAD_ROW_NUM;
            int lastRowIndex = cellExtra.getLastRowIndex() - HEAD_ROW_NUM;
            int firstColumnIndex = cellExtra.getFirstColumnIndex();
            int lastColumnIndex = cellExtra.getLastColumnIndex();

            //获取初始值 合并单元格左上角的值
            Object initValue = getInitValueFromList(firstRowIndex, firstColumnIndex, excelDataList);
            //设置值 把合并单元格左上角的值 设置到合并区域的每一个单元格
            for (int i = firstRowIndex; i <= lastRowIndex; i++) {
                for (int j = firstColumnIndex; j <= lastColumnIndex; j++) {
                    setInitValueToList(initValue, i, j, excelDataList);
                }
            }
        });
    }

    private void setInitValueToList(Object filedValue, Integer rowIndex, Integer columnIndex, List<TableDto> data) {
        TableDto object = data.get(rowIndex);

        for (Field field : object.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation != null) {
                if (annotation.index() == columnIndex) {
                    try {
                        field.set(object, filedValue);
                        break;
                    } catch (IllegalAccessException e) {
                        log.error("设置合并单元格的值异常：{}", e.getMessage());
                    }
                }
            }
        }
    }

    private Object getInitValueFromList(Integer firstRowIndex, Integer firstColumnIndex, List<TableDto> data) {
        Object filedValue = null;
        TableDto object = data.get(firstRowIndex);
        for (Field field : object.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation != null) {
                if (annotation.index() == firstColumnIndex) {
                    try {
                        filedValue = field.get(object);
                        break;
                    } catch (IllegalAccessException e) {
                        log.error("设置合并单元格的初始值异常：{}", e.getMessage());
                    }
                }
            }
        }
        return filedValue;
    }
}